from zope import schema
from zope.formlib import form
from zope.component import getMultiAdapter
from zope.interface import implements

from plone.portlets.interfaces import IPortletDataProvider
from plone.app.portlets.portlets import base
from plone.memoize.instance import memoize


from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile

from caotek.portlet.carousel import CarouselPortletMessageFactory as _


from Acquisition import aq_inner
from Products.CMFCore.utils import getToolByName


from plone.memoize import ram
from plone.memoize.compress import xhtml_compress
from plone.app.portlets.cache import render_cachekey


from DateTime.DateTime import DateTime

from random import shuffle
from string import strip
import random 


from types import UnicodeType
_default_encoding = 'utf-8'

def _encode(s, encoding=_default_encoding):
    try:
        return s.encode(encoding)
    except (TypeError, UnicodeDecodeError, ValueError):
        return s
    
def _decode(s, encoding=_default_encoding):
    try:
        return unicode(s, encoding)
    except (TypeError, UnicodeDecodeError, ValueError):
        return s


class ICarouselPortlet(IPortletDataProvider):

    name = schema.TextLine(title=_(u"Title"),
                           description=_(u"The title of the gallery. Leave blank to not display the title."),
                           default=u'',
                           required=False)
                        
    autostart = schema.Bool(title=_(u"Auto-start"),
                        description=_(u"If set carousel start automatically."),
                        required=False,
                        default=True)

    count = schema.Int(title=_(u'Maximum number of pictures to display in gallery'),
                       description=_(u'How many items to list.'),
                       required=True,
                       default=5)
    
    state = schema.Tuple(title=_(u"Workflow state"),
                         description=_(u"Items in which workflow state to show. Leave blank to not include this criterium."),
                         default=( ),
                         required=False,
                         value_type=schema.Choice(
                             vocabulary="plone.app.vocabularies.WorkflowStates"))
                         
    paths = schema.Text(title=_(u"Paths"),
                         description=_(u"List of paths to be included in searching images (it will include all sub-folders). The path is relative to the Zope root, so if your Plone side id is Plone and you would like include all folders under it, you should enter /Plone"),
                         default=(u'/'),
                         required=True)

    width = schema.Int(title=_(u'Width of the portlet'),
                        description=_(u'Width in pixels. Enter 0 to allow default portlet width.'),
                        required=True,
                        default=0)
    
    height = schema.Int(title=_(u'Height of the portlet'),
                        description=_(u'Height in pixels.'),
                        required=True,
                        default=0)
                        
    omit_border = schema.Bool(title=_(u"Omit portlet border"),
                        description=_(u"Tick this box if you want to render the text above without the standard header, border or footer."),
                        required=True,
                        default=False)
    
    display_title = schema.Bool(title=_(u"Display image title"),
                        description=_(u"Tick to let portlet gallery display title of the image."),
                        required=True,
                        default=True)
    
    display_desc = schema.Bool(title=_(u"Display image description"),
                        description=_(u"Tick to let portlet gallery display description of the image."),
                        required=True,
                        default=True)
    
#    
#    desc_font_size = schema.TextLine(title=_(u"Description font size"),
#                        description=_(u"Font size of description"),
#                        default=(u'7px'),
#                        required=True
#                        )
#
#    desc_font_color = schema.TextLine(title=_(u"Description font color"),
#                        description=_(u"Font colorption"),
#                        default=(u'#CCCCCC'),
#                        required=True
#                        )
#    
#    desc_height = schema.TextLine(title=_(u"Description height"),
#                        description=_(u"Height of description field under images."),
#                        default=(u'15px'),
#                        required=T#                        )
#
#    shuffle = schema.Bool(title=_(u"Shuffle"),
#                        description=_(u"Check to shuffle images."),
#                        default=True,
#                        required=False
#                        )
#    
    image_types = schema.Tuple(title=_(u"Image Types"),
                         description=_(u"Image types to be included into search"),
                         default=('Image', ),
                         required=False,
                         value_type=schema.Choice(
                             vocabulary="plone.app.vocabularies.PortalTypes"))
                         
#    div_id = schema.TextLine(title=_(u"ID"),
#                        description=_(u"Unique identifier for the gallery."),
#                        default=(u'slideshow'+str(random.randrange(0, 10001))),
#                        required=True
#                        )
    
    image_size = schema.TextLine(title=_(u"Image size"),
                        description=_(u"Choose image resize function (e.g. large, preview, mini, thumb, title, icon, listing) or leave blank."),
                        default=u'thumb',
                        required=False)
                        
    transition_speed = schema.Int(title=_(u'Transition Speed.'),
                       description=_(u'The time (in milliseconds) it will take to transition between two images.'),
                       required=True,
                       default=1500)

    display_time = schema.Int(title=_(u'Display Time.'),
                       description=_(u'The time (in milliseconds) to display each image.'),
                       required=True,
                       default=6000)
#
#    jquery_symbol = schema.TextLine(title=_(u"JQuery symbol"),
#                        description=_(u"JQuery introduce $ symbol, which in some versions of Plone is replaced by jq to avoid name-conflict. However in some versions it may still be $ or some of products you have installed might also changed it to $ or any different name."),
#                        default=u'jq',
#                        required=True)
#                         
                         
class Assignment(base.Assignment):
    """Portlet assignment.

    This is what is actually managed through the portlets UI and associated
    with columns.
    """

    implements(ICarouselPortlet)
    
    def __init__(self, name=u'', count=5, state=( ), paths=(u'/',), width='auto', 
                 height='auto', omit_border=False, display_title=True, 
                 display_desc=True, image_types=("Image"), 
                 image_size="thumb", transition_speed=1500, display_time=6000,autostart=False):
        self.name = name
        self.count = count
        self.state = state
        self.paths = paths
        self.width = width
        self.height = height
        self.autostart = autostart
        self.omit_border = omit_border
        self.display_title = display_title
        self.display_desc = display_desc
        self.image_types = image_types
        self.image_size = image_size
        self.transition_speed = transition_speed
        self.display_time = display_time
        
        
    @property
    def title(self):
        return _(u"Carousel Portlet")


class Renderer(base.Renderer):
    
    _template =  ViewPageTemplateFile('carouselportlet.pt')
    imageFirstId = 0
    
    def __init__(self, *args):
        
        base.Renderer.__init__(self, *args)
        
#        # For keeping style in other place than homepage
#        if not getattr(self.request,'body_style_id', False):
#            self.request.set('body_style_id','carousel')
        portal_state = getMultiAdapter((self.context, self.request), name=u'plone_portal_state')
        self.navigation_root_url = portal_state.navigation_root_url()
        self.portal = portal_state.portal()
        self.navigation_root_path = portal_state.navigation_root_path()
        self.portal_url = portal_state.portal_url()
            
    render = _template
        
    @property
    def available(self):
        return len(self._data())
        
    def images(self):
        return self._data()
        
    def title(self):
        name = self.data.name
        if name and len(strip(name))==0:
            return None
        return name
    
    def style(self):
        width = self.data.width
        style_width = width == 0 and "auto" or str(width)+"px"
         
        height = self.data.height; 
        style_height = height == 0 and "auto" or str(height)+"px"
        return "width:"+style_width+";height:"+style_height
    
    def transitionSpeed(self):
        return self.data.transition_speed
    
    def displayTime(self):
        return self.data.display_time
    
    def displayTitle(self):
        pass
    
    def autostart(self):
        return self.data.autostart
    
    @memoize
    def _data(self):
        context = aq_inner(self.context)
        catalog = getToolByName(context, 'portal_catalog')
        limit = self.data.count
        state = self.data.state
        path = self.data.paths.split("\n")
        
        criteria = {}
        criteria ['portal_type'] = 'Image'#self.data.image_types
        criteria ['sort_on'] = 'getObjPositionInParent'
        criteria ['sort_order'] = 'reverse'
        criteria ['sort_limit'] = limit
        #criteria ['state'] = state
        criteria['path'] = [_encode(p) for p in path if p != '']
        results = catalog.searchResults(**criteria)[:limit]
        items = []
        for item in results:
            details={}
            details['title']=item.pretty_title_or_id()
            details['description']=item.Description
            obj = item.getObject()
            redirect_url = item.getObject().getField('redirect').get(obj)
            item_url = item.getURL()
            details['url'] = item_url
            if redirect_url !='':
                details['redirect'] = redirect_url
            else:
                details['redirect'] = item_url
            details["image_size"] = item_url+"/image_"+self.data.image_size
            items.append(details)
        return items 

        

class AddForm(base.AddForm):
    """Portlet add form.

    This is registered in configure.zcml. The form_fields variable tells
    zope.formlib which fields to display. The create() method actually
    constructs the assignment that is being added.
    """
    form_fields = form.Fields(ICarouselPortlet)
    
    label = _(u"Add Carousel Portlet")
    description = _(u"This portlet presents dynamic carousel based on query.")

    def create(self, data):
        return Assignment(
                name=data.get('name',u''),
                count=data.get('count', 5),
                state=data.get('state', ()),
                paths=data.get('paths', u'/'),
                width=data.get('width','auto'),
                height=data.get('height','auto'),
                transition_speed=data.get('transition_speed',1500),
                display_time=data.get('display_time',6000),
                autostart=data.get('autostart', False))
        

class EditForm(base.EditForm):
    """Portlet edit form.

    This is registered with configure.zcml. The form_fields variable tells
    zope.formlib which fields to display.
    """
    form_fields = form.Fields(ICarouselPortlet)
    
    label = _(u"Edit Carousel Portlet")
    description = _(u"This portlet presents dynamic carousel.")

